package com.q3d.demo.api.hello.client.rest;

import com.alibaba.fastjson2.JSONObject;
import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.q3d.demo.api.hello.service.HelloWorldServiceInterface;
import com.q3d.demo.common.lib.service.dto.CountResultDto;
import com.q3d.demo.common.lib.service.dto.IdExtDto;
import com.q3d.demo.common.lib.service.dto.IdExtListDto;
import com.q3d.demo.common.lib.service.dto.OpResultDto;
import com.q3d.demo.common.lib.service.dto.PageRequestDto;
import com.q3d.demo.common.lib.service.dto.StringDto;
import com.q3d.demo.common.lib.service.dto.UuidDto;
import com.q3d.demo.common.lib.service.dto.UuidListDto;
import com.q3d.demo.common.lib.service.exception.ServiceException;
import com.q3d.demo.common.lib.service.response.ResponseStatus;
import com.q3d.demo.common.lib.service.response.ResponseUtil;
import com.q3d.demo.api.hello.dto.HelloWorldP1Dto;
import com.q3d.demo.api.hello.dto.HelloWorldP1K1Dto;
import com.q3d.demo.api.hello.dto.HelloWorldP1K2Dto;
import com.q3d.demo.api.hello.dto.HelloWorldP1ListDto;
import com.q3d.demo.api.hello.dto.HelloWorldR1K1Dto;
import com.q3d.demo.api.hello.dto.HelloWorldR1K1ListDto;
import com.q3d.demo.api.hello.dto.HelloWorldR1K2Dto;
import com.q3d.demo.api.hello.dto.HelloWorldR1K2ListDto;

import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

@Slf4j /** Lombok 的 Logger 注解 */
@Service
@Validated /** Controller 中某些接口的入参可能没有封装 DTO 进行校验，因此在 Service 层再做一次校验 */
/**
 * 远程接口的具体实现：RESTful 调用
 * 
 * @author 叶湘 ( weixin:yexiang841, email:yexiang841@qq.com )
 */
public class HelloWorldClientRest implements HelloWorldServiceInterface {

        @Autowired
        private RestTemplate restTemplate;

        /** 远程服务名，这是直接寻址而不经过注册中心的写法 */
        // final private String remoteSvcName = "localhost:8020";
        /** 远程服务名，这是通过注册中心寻址而不经过网关的写法 */
        // final private String remoteSvcName = "hello-svc-v1";
        /** 具体接口的路径，这是直接寻址或者通过注册中心寻址的写法 */
        // final private String remoteSvcPathPrefix = "/api/helloworld/batis";

        /** 远程服务名，这是通过网关中转的写法 */
        final private String remoteSvcName = "gateway-svc-v1";
        /** 具体接口的路径，这是通过网关中转的写法（网关服务用路径第一段寻址） */
        final private String remoteSvcPathPrefix = "/hello-svc-v1/api/helloworld/batis";

        /** Nacos 服务发现组件 */
        @NacosInjected
        private NamingService nacosNamingService;

        /** Nacos 服务组 */
        private String nacosGroupName = "group-hello-svc-v1";

        @Autowired
        private ObjectMapper objectMapper;

        /**
         * 从注册中心获取服务
         */
        protected String getUrlFromServiceCenter(String path) {
                return getUrlFromLoadBalance(path);
                // return getUrlFromIpAndPort(path);
        }

        /**
         * 通过 LoadBalance 自动寻址
         */
        protected String getUrlFromLoadBalance(String path) {
                // 自动寻址：LoadBalance 自动配置自动选择 HA 实例代替具体 {host}:{port}
                String url = String.format("http://%s%s%s", remoteSvcName, remoteSvcPathPrefix, path);
                return url;
        }

        /**
         * 获取 IP 和 PORT 手动拼装访问地址
         */
        protected String getUrlFromIpAndPort(String path) {
                try {
                        Instance instance = nacosNamingService.selectOneHealthyInstance(remoteSvcName, nacosGroupName);
                        String ip = instance.getIp();
                        int port = instance.getPort();
                        String url = String.format("http://%s:%d%s%s", ip, port, remoteSvcPathPrefix, path);
                        return url;
                } catch (NacosException e) {
                        log.warn(e.getMessage());
                        throw new ServiceException(ResponseStatus.INTERNAL_SERVER_ERROR, "Get_Target_Service_Failed");
                }
        }

        @Override
        public StringDto hello(@Valid StringDto dtoStringRequest) {
                // 从注册中心获取服务并组装 Url
                String path = "/hello/" + dtoStringRequest.getText();
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url);
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为空映射
                MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
                // 定义 request = requestHeaders + requestBody
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                // ResponseEntity<JSONObject> response =
                // restTemplate.exchange(uriBuilder.build().encode().toUri(),
                // HttpMethod.GET, request,
                // JSONObject.class);
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.GET, request,
                                JSONObject.class);
                // 根据 response 的结构自动映射响应结构体
                StringDto result = ResponseUtil.parseResponse(StringDto.class, response, remoteSvcName);
                return result;
        }

        @Override
        public UuidDto addOne(HelloWorldP1Dto helloWorldP1dto) {
                // 从注册中心获取服务并组装 Url
                String path = "/add/one";
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url);
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为映射，并且使用 ObjectMapper 工具将 DTO 直接转换成 Map
                Map<String, String> requestBody = objectMapper.convertValue(helloWorldP1dto,
                                new TypeReference<Map<String, String>>() {
                                });
                // 定义 request = requestHeaders + requestBody
                HttpEntity<Map<String, String>> request = new HttpEntity<Map<String, String>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.POST, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                UuidDto dtoUuid = ResponseUtil.parseResponse(UuidDto.class, response, remoteSvcName);
                return dtoUuid;
        }

        @Override
        public UuidListDto addBatch(@Valid HelloWorldP1ListDto dtoP1List) {
                // 从注册中心获取服务并组装 Url
                String path = "/add/batch";
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url);
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为映射，并且使用 ObjectMapper 工具将 DTO 直接转换成 Map
                Map<String, List<Map<String, Object>>> requestBody = objectMapper.convertValue(dtoP1List,
                                new TypeReference<Map<String, List<Map<String, Object>>>>() {
                                });
                // 定义 request = requestHeaders + requestBody
                HttpEntity<Map<String, List<Map<String, Object>>>> request = new HttpEntity<Map<String, List<Map<String, Object>>>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.POST, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                UuidListDto dtoUuidList = ResponseUtil.parseResponse(UuidListDto.class, response, remoteSvcName);
                return dtoUuidList;
        }

        @Override
        public OpResultDto removeOne(@Valid UuidDto dtoUuid) {
                // 从注册中心获取服务并组装 Url
                String path = "/remove/one";
                String url = this.getUrlFromServiceCenter(path);
                // 使用 UriComponentsBuilder 配置 QueryParam 参数
                UriComponentsBuilder uriBuilder = UriComponentsBuilder
                                .fromUriString(url)
                                .queryParam("uuid", dtoUuid.getUuid());
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为空映射
                MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
                // 定义 request = requestHeaders + requestBody
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.DELETE, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                OpResultDto dtoOpResult = ResponseUtil.parseResponse(OpResultDto.class, response, remoteSvcName);
                return dtoOpResult;
        }

        @Override
        public OpResultDto removeBatch(@Valid UuidListDto dtoUuidList) {
                // 从注册中心获取服务并组装 Url
                String path = "/remove/batch";
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url);
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为映射，并且使用 ObjectMapper 工具将 DTO 直接转换成 Map
                Map<String, List<Map<String, Object>>> requestBody = objectMapper.convertValue(dtoUuidList,
                                new TypeReference<Map<String, List<Map<String, Object>>>>() {
                                });
                // 定义 request = requestHeaders + requestBody
                HttpEntity<Map<String, List<Map<String, Object>>>> request = new HttpEntity<Map<String, List<Map<String, Object>>>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.DELETE, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                OpResultDto dtoOpResult = ResponseUtil.parseResponse(OpResultDto.class, response, remoteSvcName);
                return dtoOpResult;
        }

        @Override
        public OpResultDto deleteOne(@Valid IdExtDto dtoIdExt) {
                // 从注册中心获取服务并组装 Url
                String path = "/delete/one";
                String url = this.getUrlFromServiceCenter(path);
                // 使用 UriComponentsBuilder 配置 QueryParam 参数
                UriComponentsBuilder uriBuilder = UriComponentsBuilder
                                .fromUriString(url)
                                .queryParam("id", dtoIdExt.getIdExt());
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为空映射
                MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
                // 定义 request = requestHeaders + requestBody
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(
                                requestBody,
                                requestHeaders);
                // 根据 ResponseBase 的结构自动映射响应结构体
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.DELETE, request,
                                JSONObject.class);
                OpResultDto dtoOpResult = ResponseUtil.parseResponse(OpResultDto.class, response, remoteSvcName);
                return dtoOpResult;
        }

        @Override
        public OpResultDto deleteBatch(@Valid IdExtListDto dtoIdExtList) {
                // 从注册中心获取服务并组装 Url
                String path = "/delete/batch";
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url);
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为映射，并且使用 ObjectMapper 工具将 DTO 直接转换成 Map
                Map<String, List<Map<String, Object>>> requestBody = objectMapper.convertValue(dtoIdExtList,
                                new TypeReference<Map<String, List<Map<String, Object>>>>() {
                                });
                // 定义 request = requestHeaders + requestBody
                HttpEntity<Map<String, List<Map<String, Object>>>> request = new HttpEntity<Map<String, List<Map<String, Object>>>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.DELETE, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                OpResultDto dtoOpResult = ResponseUtil.parseResponse(OpResultDto.class, response, remoteSvcName);
                return dtoOpResult;
        }

        @Override
        public OpResultDto reviveOne(@Valid IdExtDto dtoIdExt) {
                // 从注册中心获取服务并组装 Url
                String path = "/revive/one";
                String url = this.getUrlFromServiceCenter(path);
                // 使用 UriComponentsBuilder 配置 QueryParam 参数
                UriComponentsBuilder uriBuilder = UriComponentsBuilder
                                .fromUriString(url)
                                .queryParam("id", dtoIdExt.getIdExt());
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为空映射
                MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
                // 定义 request = requestHeaders + requestBody
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.PUT, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                OpResultDto dtoOpResult = ResponseUtil.parseResponse(OpResultDto.class, response, remoteSvcName);
                return dtoOpResult;
        }

        @Override
        public OpResultDto reviveBatch(@Valid IdExtListDto dtoIdExtList) {
                // 从注册中心获取服务并组装 Url
                String path = "/revive/batch";
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url);
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为映射，并且使用 ObjectMapper 工具将 DTO 直接转换成 Map
                Map<String, List<Map<String, Object>>> requestBody = objectMapper.convertValue(dtoIdExtList,
                                new TypeReference<Map<String, List<Map<String, Object>>>>() {
                                });
                // 定义 request = requestHeaders + requestBody
                HttpEntity<Map<String, List<Map<String, Object>>>> request = new HttpEntity<Map<String, List<Map<String, Object>>>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.PUT, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                OpResultDto dtoOpResult = ResponseUtil.parseResponse(OpResultDto.class, response, remoteSvcName);
                return dtoOpResult;
        }

        @Override
        public OpResultDto editSelective(@Valid HelloWorldP1K1Dto dtoP1K1) {
                // 从注册中心获取服务并组装 Url
                String path = "/edit/selective";
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url);
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为映射，并且使用 ObjectMapper 工具将 DTO 直接转换成 Map
                Map<String, Object> requestBody = objectMapper.convertValue(dtoP1K1,
                                new TypeReference<Map<String, Object>>() {
                                });
                // 若使用 query 传参则写入 UriBuilder
                for (Entry<String, Object> entity : requestBody.entrySet()) {
                        uriBuilder.queryParam(entity.getKey(), entity.getValue());
                }
                // 定义 request = requestHeaders + requestBody
                HttpEntity<Map<String, Object>> request = new HttpEntity<Map<String, Object>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.PUT, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                OpResultDto dtoOpResult = ResponseUtil.parseResponse(OpResultDto.class, response, remoteSvcName);
                return dtoOpResult;
        }

        @Override
        public OpResultDto updateSelective(@Valid HelloWorldP1K2Dto dtoP1K2) {
                // 从注册中心获取服务并组装 Url
                String path = "/edit/selective";
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url);
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为映射，并且使用 ObjectMapper 工具将 DTO 直接转换成 Map
                Map<String, Object> requestBody = objectMapper.convertValue(dtoP1K2,
                                new TypeReference<Map<String, Object>>() {
                                });
                // 若使用 query 传参则写入 UriBuilder
                for (Entry<String, Object> entity : requestBody.entrySet()) {
                        uriBuilder.queryParam(entity.getKey(), entity.getValue());
                }
                // 定义 request = requestHeaders + requestBody
                HttpEntity<Map<String, Object>> request = new HttpEntity<Map<String, Object>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.PUT, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                OpResultDto dtoOpResult = ResponseUtil.parseResponse(OpResultDto.class, response, remoteSvcName);
                return dtoOpResult;
        }

        @Override
        public CountResultDto getCount() {
                // 从注册中心获取服务并组装 Url
                String path = "/get/count";
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url);
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为空映射
                MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
                // 定义 request = requestHeaders + requestBody
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.GET, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                CountResultDto dtoCountResult = ResponseUtil.parseResponse(CountResultDto.class, response,
                                remoteSvcName);
                return dtoCountResult;
        }

        @Override
        public HelloWorldR1K1Dto getOne(@Valid UuidDto dtoUuid) {
                // 从注册中心获取服务并组装 Url
                String path = "/get/one/" + dtoUuid.getUuid();
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url);
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为空映射
                MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
                // 定义 request = requestHeaders + requestBody
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.GET, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                HelloWorldR1K1Dto dtoR1K1 = ResponseUtil.parseResponse(HelloWorldR1K1Dto.class, response,
                                remoteSvcName);
                return dtoR1K1;
        }

        @Override
        public HelloWorldR1K1ListDto getBatch(@Valid UuidListDto dtoUuidList) {
                // 从注册中心获取服务并组装 Url
                String path = "/get/batch";
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url);
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为映射，并且使用 ObjectMapper 工具将 DTO 直接转换成 Map
                Map<String, List<Map<String, Object>>> requestBody = objectMapper.convertValue(dtoUuidList,
                                new TypeReference<Map<String, List<Map<String, Object>>>>() {
                                });
                // 定义 request = requestHeaders + requestBody
                HttpEntity<Map<String, List<Map<String, Object>>>> request = new HttpEntity<Map<String, List<Map<String, Object>>>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.POST, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                HelloWorldR1K1ListDto dtoR1K1List = ResponseUtil.parseResponse(HelloWorldR1K1ListDto.class,
                                response,
                                remoteSvcName);
                return dtoR1K1List;
        }

        @Override
        public HelloWorldR1K1ListDto getByPage(@Valid PageRequestDto dtoPageRequest) {
                // 从注册中心获取服务并组装 Url
                String path = "/get/page";
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder
                                .fromUriString(url)
                                .queryParam("page", dtoPageRequest.getPage())
                                .queryParam("limit", dtoPageRequest.getLimit());
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为空映射
                MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
                // 定义 request = requestHeaders + requestBody
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.GET, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                HelloWorldR1K1ListDto dtoR1K1List = ResponseUtil.parseResponse(HelloWorldR1K1ListDto.class,
                                response,
                                remoteSvcName);
                return dtoR1K1List;
        }

        @Override
        public UuidListDto getUuidByPage(@Valid PageRequestDto dtoPageRequest) {
                // 从注册中心获取服务并组装 Url
                String path = "/get/uuid/page";
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder
                                .fromUriString(url)
                                .queryParam("page", dtoPageRequest.getPage())
                                .queryParam("limit", dtoPageRequest.getLimit());
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为空映射
                MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
                // 定义 request = requestHeaders + requestBody
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.GET, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                UuidListDto dtoUuidList = ResponseUtil.parseResponse(UuidListDto.class,
                                response,
                                remoteSvcName);
                return dtoUuidList;
        }

        @Override
        public CountResultDto selectCount() {
                // 从注册中心获取服务并组装 Url
                String path = "/select/count";
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url);
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为空映射
                MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
                // 定义 request = requestHeaders + requestBody
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.GET, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                CountResultDto dtoCountResult = ResponseUtil.parseResponse(CountResultDto.class, response,
                                remoteSvcName);
                return dtoCountResult;
        }

        @Override
        public CountResultDto selectCountRemoved() {
                // 从注册中心获取服务并组装 Url
                String path = "/select/count/removed";
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url);
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为空映射
                MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
                // 定义 request = requestHeaders + requestBody
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.GET, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                CountResultDto dtoCountResult = ResponseUtil.parseResponse(CountResultDto.class, response,
                                remoteSvcName);
                return dtoCountResult;
        }

        @Override
        public HelloWorldR1K2Dto selectOne(@Valid IdExtDto dtoIdExt) {
                // 从注册中心获取服务并组装 Url
                String path = "/select/one/" + dtoIdExt.getIdExt();
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url);
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为空映射
                MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
                // 定义 request = requestHeaders + requestBody
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.GET, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                HelloWorldR1K2Dto dtoR1K2 = ResponseUtil.parseResponse(HelloWorldR1K2Dto.class, response,
                                remoteSvcName);
                return dtoR1K2;
        }

        @Override
        public HelloWorldR1K2ListDto selectBatch(@Valid IdExtListDto dtoIdExtList) {
                // 从注册中心获取服务并组装 Url
                String path = "/select/batch";
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url);
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为映射，并且使用 ObjectMapper 工具将 DTO 直接转换成 Map
                Map<String, List<Map<String, Object>>> requestBody = objectMapper.convertValue(dtoIdExtList,
                                new TypeReference<Map<String, List<Map<String, Object>>>>() {
                                });
                // 定义 request = requestHeaders + requestBody
                HttpEntity<Map<String, List<Map<String, Object>>>> request = new HttpEntity<Map<String, List<Map<String, Object>>>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.POST, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                HelloWorldR1K2ListDto dtoR1K2List = ResponseUtil.parseResponse(HelloWorldR1K2ListDto.class,
                                response,
                                remoteSvcName);
                return dtoR1K2List;
        }

        @Override
        public HelloWorldR1K2ListDto selectByPage(@Valid PageRequestDto dtoPageRequest) {
                // 从注册中心获取服务并组装 Url
                String path = "/select/page";
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder
                                .fromUriString(url)
                                .queryParam("page", dtoPageRequest.getPage())
                                .queryParam("limit", dtoPageRequest.getLimit());
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为空映射
                MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
                // 定义 request = requestHeaders + requestBody
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.GET, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                HelloWorldR1K2ListDto dtoR1K2List = ResponseUtil.parseResponse(HelloWorldR1K2ListDto.class,
                                response,
                                remoteSvcName);
                return dtoR1K2List;
        }

        @Override
        public IdExtListDto selectIdExtByPage(@Valid PageRequestDto dtoPageRequest) {
                // 从注册中心获取服务并组装 Url
                String path = "/select/id/page";
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder
                                .fromUriString(url)
                                .queryParam("page", dtoPageRequest.getPage())
                                .queryParam("limit", dtoPageRequest.getLimit());
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为空映射
                MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
                // 定义 request = requestHeaders + requestBody
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.GET, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                IdExtListDto dtoIdExtList = ResponseUtil.parseResponse(IdExtListDto.class,
                                response,
                                remoteSvcName);
                return dtoIdExtList;
        }

        @Override
        public IdExtListDto selectIdExtRemoved() {
                // 从注册中心获取服务并组装 Url
                String path = "/select/id/removed";
                String url = this.getUrlFromServiceCenter(path);
                UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url);
                // 定义 requestHeaders
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.setContentType(MediaType.APPLICATION_JSON);
                // 定义 requestBody 为空映射
                MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
                // 定义 request = requestHeaders + requestBody
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(
                                requestBody,
                                requestHeaders);
                // 此处是远程调用
                ResponseEntity<JSONObject> response = restTemplate.exchange(uriBuilder.build().encode().toUri(),
                                HttpMethod.GET, request,
                                JSONObject.class);
                // 根据 ResponseBase 的结构自动映射响应结构体
                IdExtListDto dtoIdExtList = ResponseUtil.parseResponse(IdExtListDto.class,
                                response,
                                remoteSvcName);
                return dtoIdExtList;
        }

}
